]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | import Foundation | |
3 | ||
4 | class FlatBezelObjectCell: QSObjectCell { | |
5 | override func preferredImagePosition() -> NSControl.ImagePosition { | |
6 | return .imageAbove | |
7 | } | |
8 | ||
9 | override func draw(withFrame cellFrame: NSRect, in controlView: NSView?) { | |
10 | if let controlView { | |
11 | ||
12 | let isFirstResponder = controlView.window?.firstResponder == controlView && !(controlView is NSTableView) | |
13 | let dropTarget = isHighlighted && ((highlightsBy.rawValue & NSCell.StyleMask.changeBackgroundCellMask.rawValue) != 0) && !isBezeled | |
14 | ||
15 | var fillColor: NSColor? | |
16 | let strokeColor = NSColor.clear | |
17 | ||
18 | if isFirstResponder { | |
19 | fillColor = self.highlightColor() | |
20 | } else { | |
21 | fillColor = self.backgroundColor | |
22 | } | |
23 | ||
24 | if dropTarget { | |
25 | fillColor = NSColor(red: 0.77, green: 0.91, blue: 0.96, alpha: 1) | |
26 | } | |
27 | ||
28 | fillColor?.setFill() | |
29 | strokeColor.setStroke() | |
30 | ||
31 | let roundRect = NSBezierPath() | |
32 | roundRect.append(withRoundedRectangle: cellFrame, withRadius: cellRadiusFactor()) | |
33 | roundRect.fill() | |
34 | ||
35 | drawInterior(withFrame: drawingRect(forBounds: cellFrame), in: controlView) | |
36 | } | |
37 | } | |
38 | ||
39 | override func titleRect(forBounds _rect: NSRect) -> NSRect { | |
40 | var rect = _rect | |
41 | rect = NSOffsetRect(rect, 0, -4) | |
42 | return super.titleRect(forBounds: rect) | |
43 | } | |
44 | ||
45 | override func drawText(for drawObject: QSObject!, withFrame cellFrame: NSRect, in controlView: NSView!) { | |
46 | if imagePosition == .imageOnly { | |
47 | return | |
48 | } | |
49 | ||
50 | var abbrString: String? = nil | |
51 | ||
52 | if controlView.responds(to: #selector(QSSearchObjectView.matchedString)) { | |
53 | abbrString = (controlView as! QSSearchObjectView).matchedString() | |
54 | } | |
55 | ||
56 | var nameString: String? = nil | |
57 | var hitMask: NSIndexSet? = nil | |
58 | ||
59 | let ranker = drawObject.ranker() | |
60 | if ranker != nil && abbrString != nil { | |
61 | nameString = ranker?.matchedString(forAbbreviation: abbrString, hitmask: &hitMask, inContext: nil) | |
62 | } | |
63 | ||
64 | if (nameString == nil) { | |
65 | nameString = drawObject.displayName() | |
66 | } | |
67 | ||
68 | let rankedStringIsName = nameString == drawObject.displayName() || nameString == nil | |
69 | ||
70 | if nameString == nil { | |
71 | nameString = drawObject.identifier() ?? "Unknown" | |
72 | } | |
73 | ||
74 | let useAlternateColor = controlView is NSTableView && (controlView as! NSTableView).isRowSelected((controlView as! NSTableView).row(at: cellFrame.origin)) | |
75 | let mainColor = textColor() ?? (useAlternateColor ? .alternateSelectedControlTextColor : .controlTextColor) | |
76 | let fadedColor = mainColor.withAlphaComponent(0.50) | |
77 | let textDrawRect = titleRect(forBounds: cellFrame) | |
78 | ||
79 | ||
80 | let titleString = NSMutableAttributedString(string: nameString!) | |
81 | let nameAttributes = (value(forKey: "nameAttributes") as? [NSAttributedString.Key : Any]) | |
82 | let detailsAttributes = (value(forKey: "detailsAttributes") as? [NSAttributedString.Key : Any]) | |
83 | titleString.setAttributes(rankedStringIsName ? nameAttributes : detailsAttributes, range: NSMakeRange(0, titleString.length)) | |
84 | ||
85 | if abbrString != nil && abbrString!.hasPrefix("QSActionMnemonic") { | |
86 | titleString.addAttribute(.foregroundColor, value: rankedStringIsName ? fadedColor : fadedColor.withAlphaComponent(0.8), range: NSMakeRange(0, titleString.length)) | |
87 | ||
88 | var hits: Int = 0 | |
89 | let count = hitMask?.getIndexes(&hits, maxCount: titleString.length, inIndexRange: nil) | |
90 | for i in 0..<(count ?? 0) { | |
91 | for j in 1.. { | |
92 | } | |
93 | } | |
94 | } | |
95 | } | |
96 | ||
97 | NSUInteger i = 0; | |
98 | NSUInteger j = 0; | |
99 | NSUInteger hits[[titleString length]]; | |
100 | NSUInteger count = [hitMask getIndexes:(NSUInteger *)&hits maxCount:[titleString length] inIndexRange:nil]; | |
101 | NSDictionary *attributes = @{ | |
102 | NSForegroundColorAttributeName: rankedStringIsName ? mainColor : fadedColor | |
103 | }; | |
104 | for(i = 0; i<count; i += j) { | |
105 | for (j = 1; i+j<count && hits[i+j-1] +1 == hits[i+j]; j++); | |
106 | [titleString addAttributes:attributes range:NSMakeRange(hits[i], j)]; | |
107 | } | |
108 | } else { | |
109 | [titleString addAttribute:NSBaselineOffsetAttributeName value:[NSNumber numberWithDouble:-1.0] range:NSMakeRange(0, [titleString length])]; | |
110 | } | |
111 | ||
112 | if (showDetails) { | |
113 | NSString *detailsString = [drawObject details]; | |
114 | ||
115 | NSRange returnRange = [detailsString rangeOfString:@"\n"]; | |
116 | if (returnRange.location != NSNotFound) { | |
117 | detailsString = [detailsString substringToIndex:returnRange.location]; | |
118 | } | |
119 | ||
120 | detailsAttributes = [detailsAttributes mutableCopy]; | |
121 | [detailsAttributes setValue:[NSColor grayColor] forKey:NSForegroundColorAttributeName]; | |
122 | ||
123 | if (detailsString && detailsString.length && ![detailsString isEqualToString:nameString]) { | |
124 | [titleString appendAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n%@",detailsString] attributes:detailsAttributes] autorelease]]; | |
125 | } | |
126 | } | |
127 | ||
128 | NSRect centerRect = rectFromSize([titleString size]); | |
129 | centerRect.size.width = NSWidth(textDrawRect); | |
130 | centerRect.size.height = MIN(NSHeight(textDrawRect), centerRect.size.height); | |
131 | [titleString drawInRect:centerRectInRect(centerRect, textDrawRect)]; | |
132 | } | |
133 | ||
134 | - (void)drawSearchPlaceholderWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { | |
135 | NSString *defaultText = NSLocalizedStringWithDefaultValue(@"Type to search", nil, [NSBundle mainBundle], @"Type to search", @"Hint that appears in the first pane of the QS interface when it's empty."); | |
136 | NSSize textSize = [defaultText sizeWithAttributes:nameAttributes]; | |
137 | NSRect textRect = centerRectInRect(rectFromSize(textSize), cellFrame); | |
138 | BOOL isFirstResponder = [[controlView window] firstResponder] == controlView && ![controlView isKindOfClass:[NSTableView class]]; | |
139 | ||
140 | if (isFirstResponder && [controlView isKindOfClass:[QSSearchObjectView class]]) { | |
141 | NSImage *find = [NSImage imageWithSystemSymbolName:@"magnifyingglass.circle.fill" accessibilityDescription:nil]; | |
142 | ||
143 | ||
144 | [find setSize:QSSize16]; | |
145 | NSRect findImageRect = expelRectFromRectOnEdge(centerRectInRect(rectFromSize([find size]), cellFrame), textRect, NSRectEdgeMinX, -2); | |
146 | ||
147 | ||
148 | NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext]; | |
149 | [graphicsContext saveGraphicsState]; | |
150 | CGContextRef context = [graphicsContext CGContext]; | |
151 | CGContextBeginTransparencyLayerWithRect(context, findImageRect, nil); | |
152 | CGContextSetBlendMode(context, kCGBlendModeNormal); | |
153 | [find drawInRect:findImageRect fromRect:rectFromSize([find size]) operation:NSCompositingOperationSourceOver fraction:1]; | |
154 | CGContextSetBlendMode(context, kCGBlendModeSourceIn); | |
155 | CGContextSetFillColorWithColor(context, [[NSColor textColor] CGColor]); | |
156 | CGContextFillRect(context, findImageRect); | |
157 | CGContextEndTransparencyLayer(context); | |
158 | ||
159 | [defaultText drawInRect:textRect withAttributes:nameAttributes]; | |
160 | } | |
161 | } | |
162 | ||
163 | @end | |
164 | */ |